package com.qcby.mycommunity_003.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qcby.mycommunity_003.annotation.LogAnnotation;
import com.qcby.mycommunity_003.configuration.ApiConfiguration;
import com.qcby.mycommunity_003.entity.Community;
import com.qcby.mycommunity_003.entity.Person;
import com.qcby.mycommunity_003.entity.User;
import com.qcby.mycommunity_003.mapper.PersonMapper;
import com.qcby.mycommunity_003.service.CommunityService;
import com.qcby.mycommunity_003.service.PersonService;
import com.qcby.mycommunity_003.util.*;
import com.qcby.mycommunity_003.vo.AddFaceVo;
import com.qcby.mycommunity_003.vo.PageVo;
import com.qcby.mycommunity_003.vo.PersonListVo;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author admin
 * @since 2024-03-27
 */
@RestController
@RequestMapping("/sys/person")
public class PersonController {
    @Autowired
    private PersonService personService;
    @Autowired
    private CommunityService communityService;
    @Autowired
    private PersonMapper personMapper;
    @Autowired
    private ApiConfiguration apiConfiguration;
    @Value("${upload.face}")
    private String face;
    @Value("${upload.urlPrefix}")
    private String urlPrefix;
    @Value("${upload.excel}")
    private String excel;

    /**
     * 居民列表展示
     * @param personListVo
     * @return
     */
    @GetMapping("/list")
    public Result PersonList(PersonListVo personListVo){
        HashMap<String,Object> map=new HashMap();
        map=personService.PersonList(personListVo);
        map.put("communityList", communityService.list());
        return Result.ok().put("data",map);
    }

    /**
     * 添加住户
     * @param person
     * @param session
     * @return
     */
    @LogAnnotation("添加用户")
    @PostMapping("/add")
   public Result AddPerson(@RequestBody Person person, HttpSession session){
        User user = (User) session.getAttribute("user");
        person.setCreater(user.getUsername());
        int insert = personMapper.insert(person);
        if(insert==0){
            return Result.error("插入失败");
        }
        return Result.ok();
   }

    /**
     * 通过id查找做回显
     * @param person_id
     * @return
     */
    @GetMapping("/info/{person_id}")
    public Result getById(@PathVariable("person_id") Integer person_id){
        HashMap<String ,Object> map=new HashMap<>();
        //小区列表
        List<Community> communityList = communityService.list();
        map.put("communityList",communityList);
        //居民信息
        Person person = personMapper.selectById(person_id);
        map.put("person",person);
        return Result.ok().put("data",map);
    }

    /**
     * 修改居民
     * @param person
     * @return
     */
    @LogAnnotation("修改用户")
    @PutMapping("/edit")
    public Result updatePer(@RequestBody Person person){
        QueryWrapper <Person> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("person_id",person.getPersonId());
        personMapper.update(person,queryWrapper);
        return Result.ok();
    }

    /**
     * 删除居民
     * @param ids
     * @return
     */
    @LogAnnotation("删除用户")
    @DeleteMapping("/del")
    public Result delPerson(@RequestBody List<Integer> ids){
        personMapper.deleteBatchIds(ids);
        return Result.ok();
    }

    /**
     * 进行人脸识别
     * 两种方式：调用腾讯api接口，或者自己模拟
     * @param personFaceForm
     * @return
     */
    @LogAnnotation("人脸识别录入")
    @PostMapping("/addPerson")
    public Result addFace(@RequestBody AddFaceVo personFaceForm){
        //1============严谨性判断
        Person person = personService.getById(personFaceForm.getPersonId());
        if(person==null){
            return Result.error("居民不存在");
        }
        if(personFaceForm.getFileBase64()==null||personFaceForm.getFileBase64().equals("")){
          return Result.error("请上传base64编码的文件");
        }
        //1.腾讯接口使用的是腾讯优图祖母模型，
        if(apiConfiguration.isUsed()){
            //**************方法一：调用腾讯api识别。
            String faceId = newPerson(personFaceForm, person.getUserName());
            String faceBase = personFaceForm.getFileBase64().substring(0, 60);
//            ************方法二：自己模拟判断是不是人脸图片************：
//            String faceId = RandomUtil.getBitRandom();
////            //如果不是头像(这一行如果不注释就报错)
//            if(faceBase.equals("iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAAXNSR0IArs4c")) {
//                return Result.error("人脸识别失败");
//            }
            //2.存到本地的文件夹内
//            //存储头像
            String filename = faceId + "." + personFaceForm.getExtName();
//            String savePath = face + filename;
//            try {
//                Base64Util.decoderBase64File(personFaceForm.getFileBase64(), savePath);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
            //**********************这是方法一结束*****************：
            //生成头像访问路径
            String faceUrl = urlPrefix + "community/upload/face/" + filename;
            person.setFaceUrl(faceUrl);
            person.setState(2);
            person.setFaceBase(faceBase);
            //3.存到数据库中（包括base64编码存储）
            //更新人脸识别状态及图片地址
            this.personService.updateById(person);
            return Result.ok();
        }
        return Result.error("未开启人脸识别");
    }

    /**
     * 腾讯api接口相关
     * @param vo
     * @param personName
     * @return
     */
    private String newPerson(AddFaceVo vo,String personName) {
        //id base64 拓展名 人员的名字
        String faceId = null;
        String faceBase64 = vo.getFileBase64();
        String extname = vo.getExtName();
        String personId = vo.getPersonId()+"";
        String savePath = face;
        if (faceBase64!=null && !faceBase64.equals("")) {
            FaceApi faceApi = new FaceApi();
            RootResp resp = faceApi.newperson(apiConfiguration, personId, personName, faceBase64);
            if(resp.getRet()==0) {
                JSONObject data = JSON.parseObject(resp.getData().toString());
                faceId = data.getString("FaceId");
                if(faceId!=null) {
                    String filename = faceId + "." + extname;
                    savePath += filename;
                    try {
                        //调用自定义工具类，将base64编码文件解码，并报存在指定路径
                        Base64Util.decoderBase64File(faceBase64, savePath);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            else {
                return faceId;
            }
        }
        return faceId;
    }

    /**
     * 将本页码的居民信息导出
     * @param personListVo
     * @return
     */
    @LogAnnotation("居民信息导出")
    @GetMapping("/exportExcel")
    private Result exportExcel(PersonListVo personListVo){
        //先查出本页的数据，封装list。
        HashMap<String, Object> map = personService.PersonList(personListVo);
        PageVo pageVo= (PageVo)map.get("pageList");
        List list=pageVo.getList();
        String path=excel;
        //调用工具类存入本地，这里使用的是io流
        path=ExcelUtil.ExpPersonInfo(list,path);
        return Result.ok().put("data",path);
    }

    /**uploadExcel
     * 导入文件
     * @RequestParam("uploadExcel")强制绑定
     * @param uploadExcel
     * @return
     */
    @LogAnnotation("导入文件")
    @PostMapping("/excelUpload")
    private Result excelUpload(MultipartFile uploadExcel) throws IOException {
        //严谨性判断，如果没有文件
        if(uploadExcel.getOriginalFilename().equals("")){
            return Result.error("没有选中文件");
        }else {
            //1.使用uuid工具生成唯一文件名
            String filename=UUID.randomUUID().toString();
            //2.获取原文件名
           String originname= uploadExcel.getOriginalFilename();
            //3.获取拓展名后缀
            String extName=originname.substring(originname.lastIndexOf("."));
            //4.拼接uuid文件名和后缀生成新的文件名
            String newFileName=filename+extName;
            //5.根据excel和文件名创建文件
            File targetfile = new File(excel, newFileName);
            //6.spring框架提供的一个文件保存的接口，将文件保存到指定的文件目录下
            uploadExcel.transferTo(targetfile);
            return Result.ok().put("data",newFileName);
        }
    }

    /**
     * 数据上传
     * @param fileName
     * @param session
     * @return
     */
    @LogAnnotation("居民信息导入")
    @PostMapping("/parsefile/{fileName}")
    public Result parsefile(@PathVariable("fileName") String fileName,HttpSession session){
        User user = (User) session.getAttribute("user");
        //有关excel表的两个类
        POIFSFileSystem fs = null;
        HSSFWorkbook wb = null;
        try {
            String basePath = excel + fileName;
            fs = new POIFSFileSystem(new FileInputStream(basePath));
            wb = new HSSFWorkbook(fs);
        } catch (Exception e) {
            e.printStackTrace();
        }
        HSSFSheet sheet = wb.getSheetAt(0);
        //二维数组定位
        Object[][] data = null;
        int r = sheet.getLastRowNum()+1;
        int c = sheet.getRow(0).getLastCellNum();
        int headRow = 2;
        data = new Object[r - headRow][c];
        //将数据复制进二维数组进去
        for (int i = headRow; i < r; i++) {
            HSSFRow row = sheet.getRow(i);
            for (int j = 0; j < c; j++) {
                HSSFCell cell = null;
                try {
                    cell = row.getCell(j);
                    try {
                        cell = row.getCell(j);
                        DataFormatter dataFormater = new DataFormatter();
                        String a = dataFormater.formatCellValue(cell);
                        data[i - headRow][j] = a;
                    } catch (Exception e) {
                        data[i-headRow][j] = "";
                        if(j==0){
                            try {
                                double d = cell.getNumericCellValue();
                                data[i - headRow][j] = (int)d + "";
                            }catch(Exception ex){
                                data[i-headRow][j] = "";
                            }
                        }
                    }
                } catch (Exception e) {
                    System.out.println("i="+i+";j="+j+":"+e.getMessage());
                }
            }
        }
        //封装对象
        int row = data.length;
        int col = 0;
        String errinfo = "";
        headRow = 3;
        String[] stitle={"ID","小区名称","所属楼栋","房号","姓名","性别","手机号码","居住性质","状态","备注"};
        errinfo = "";
        for (int i = 0; i < row; i++) {
            Person single = new Person();
            single.setPersonId(0);
            single.setState(1);
            single.setFaceUrl("");
            try {
                col=1;
                String communityName = data[i][col++].toString();
                QueryWrapper<Community> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("community_name", communityName);
                Community community = this.communityService.getOne(queryWrapper);
                if( community == null){
                    errinfo += "Excel文件第" + (i + headRow) + "行小区名称不存在！";
                    return Result.ok().put("status", "fail").put("data", errinfo);
                }
                single.setCommunityId(community.getCommunityId());
                single.setTermName(data[i][col++].toString());
                single.setHouseNo(data[i][col++].toString());
                single.setUserName(data[i][col++].toString());
                single.setSex(data[i][col++].toString());
                single.setMobile(data[i][col++].toString());
                single.setPersonType(data[i][col++].toString());
                single.setRemark(data[i][col++].toString());
                single.setCreater(user.getUsername());
                this.personService.save(single);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return Result.ok().put("status", "success").put("data","数据导入完成！");
    }


}

